package jxerializeml;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * This class decides which fields are serializable or not.
 * 
 * @author Tomáš Zíma
 */
public class PolicyManager {
	private Class<?>                serializedClass     = null;
	private List<FieldModifier>     bannedModifiers     = new ArrayList<>();
	private final FieldModifier[]   defBannedModifiers  = new FieldModifier[] {
		FieldModifier.TRANSIENT, FieldModifier.FINAL
	};
	
	/**
	 * Set up a object, which will be serialized.
	 * 
	 * @param serializedObject
	 *     An object, which will be serialized.
	 */
	public PolicyManager(Object serializedObject) {
		this.serializedClass = serializedObject.getClass();
		
		for (FieldModifier defBannedModifier : defBannedModifiers) {
			bannedModifiers.add(defBannedModifier);
		}
	}
	
	/**
	 * Clear list of banned (non-serializable) modifiers.
	 */
	public void clearBannedModifiers() {
		bannedModifiers.clear();
	}
	
	/**
	 * Adds a new modifier, which will become non-serializable.
	 * 
	 * @param fieldModifier
	 *     A modifier, which will become non-serializable.
	 */
	public void addBannedModifier(FieldModifier fieldModifier) {
		bannedModifiers.add(fieldModifier);
	}
	
	/**
	 * @return
	 *     List of fields, which are serializable.
	 */
	public List<Field> getSerializableFields() {
		Field       fields[]    = serializedClass.getDeclaredFields();
		List<Field> result      = new ArrayList<>();
		
		for (Field field : fields) {
			field.setAccessible(true);
			
			if (isSerializable(field)) {
				result.add(field);
			}
		}
		
		return result;
	}
	
	/**
	 * Checks if field is serializable.
	 * 
	 * @param field
	 *     Field to be checked.
	 *     
	 * @return
	 *     True if field is serializable.
	 */
	protected boolean isSerializable(Field field) {
		for (FieldModifier fieldModifier : bannedModifiers) {
			if (fieldModifier.equals(field)) {
				return false;
			}
		}
		
		return true;
	}
}
